package com.karson.service.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.hash.Hash;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.karson.common.config.redis.RedisConfig;
import com.karson.common.constants.BusinessConstants;
import com.karson.common.constants.Constants;
import com.karson.common.dto.TopKDTO;
import com.karson.common.exception.AsmrException;
import com.karson.common.model.*;
import com.karson.common.request.AlbumRequest;
import com.karson.common.request.AlbumSearchRequest;
import com.karson.common.response.AlbumRJCode;
import com.karson.common.response.AlbumResponse;
import com.karson.common.response.AlbumTrackResponse;
import com.karson.common.response.TrackResponse;
import com.karson.common.util.AsmrUtil;
import com.karson.common.util.RedisUtil;
import com.karson.common.vo.HotWorkVo;
import com.karson.service.dao.*;
import com.karson.service.service.*;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.sound.midi.Track;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
* @author ZKS
* @description 针对表【ar_album_info(专辑信息)】的数据库操作Service实现
* @createDate 2025-07-10 13:41:05
*/
@Service
public class AlbumInfoServiceImpl extends ServiceImpl<AlbumInfoMapper, AlbumInfo>
    implements AlbumInfoService{
    @Autowired
    private AlbumInfoMapper albumInfoMapper;
    @Autowired
    private AlbumTagsService albumTagsService;
    @Autowired
    private TagInfoService tagInfoService;
    @Autowired
    private AuthorService authorService;
    @Autowired
    private AlbumAuthorService albumAuthorService;
    @Autowired
    private CirclesInfoService circlesInfoService;
    @Autowired
    private ActionCountsService actionCountsService;
    @Autowired
    private TrackInfoMapper trackInfoMapper;
    @Autowired
    private BehaviorWeightMapper behaviorWeightMapper;
    @Autowired
    private RedisUtil redisUtil;
    @Autowired
    private PersonalizedPushService personalizedPushService;

    @Override
    public IPage<AlbumResponse> pageList(IPage<AlbumResponse> albumResponseIPage, AlbumSearchRequest albumSearchRequest) {
        return  albumInfoMapper.getPageList(albumResponseIPage,albumSearchRequest);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveAlbumInfo(AlbumRequest albumRequest) {
        AlbumInfo albumInfo = saveOrUpdateGenAlbumInfo(albumRequest);
        albumRequest.setId(albumInfo.getId());
        // 初始化专辑基础信息（播放量，订阅量等）
        ActionCounts albumCount = new ActionCounts();
        albumCount.setType(BusinessConstants.BUSINESS_ALBUM);
        albumCount.setMessageId(albumRequest.getId());
        // 设置业务ID
        albumCount.setFavoriteCount(0);
        albumCount.setDislikeCount(0);
        albumCount.setLikeCount(0);
        actionCountsService.save(albumCount);
        personalizedPushService.pushLabelStockIn(albumRequest);
    }

    /**
     * 保存元信息
     * @param albumRequest
     * @return
     */
    private AlbumInfo saveOrUpdateGenAlbumInfo(AlbumRequest albumRequest){
        List<Integer> tags = albumRequest.getTags();
        if (tags.size() > 20){
            throw new AsmrException("标签数量过多");
        }
        List<Integer> authorId = albumRequest.getAuthorId();
        if (authorId.size() > 10){
            throw new AsmrException("作者人数过多，如有需要请联系管理员");
        }
        AlbumInfo albumInfo = BeanUtil.copyProperties(albumRequest, AlbumInfo.class);
        Integer circleId = albumRequest.getCircleId();
        if (circleId == null) {
            throw new AsmrException("circleId is null");
        }
        // 社团作品数 + 1
        circlesInfoService.operationWorkCount(circleId,1,Constants.WORK_COUNT_ADD);
        super.saveOrUpdate(albumInfo);
        // 保存作品和作者的关联信息
        List<AlbumAuthor> albumAuthors = new ArrayList<>();
        for (Integer id : authorId) {
            // 作者作品数加1
            authorService.operationWorkCount(id,1,Constants.WORK_COUNT_ADD);
            AlbumAuthor albumAuthor = new AlbumAuthor();
            albumAuthor.setAuthorId(id);
            albumAuthor.setAlbumId(albumInfo.getId());
            albumAuthors.add(albumAuthor);
        }
        albumAuthorService.saveBatch(albumAuthors);
        //标签作品关联信息

        List<ArAlbumTag> saveList = new ArrayList<>();

        for (Integer tagId : tags) {
            //标签数量新增
            tagInfoService.operationWorkCount(tagId,1,Constants.WORK_COUNT_ADD);
            // 保存关联关系
            ArAlbumTag tag = new ArAlbumTag();
            tag.setAlbumId(albumInfo.getId());
            tag.setTagId(tagId);
            // 这里默认保存持久化状态
            tag.setStatus(Constants.TAG_NORMAL);
            saveList.add(tag);
        }
        albumTagsService.saveBatch(saveList);

        return albumInfo;
    }

    @Override
    public AlbumResponse getAlbumInfoById(Integer albumId) {
        return albumInfoMapper.getAllAlbumInfoById(albumId);
    }

    @Override
    public AlbumResponse getAllAlbumById(Integer albumId) {
        return albumInfoMapper.getAllAlbumInfoById(albumId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removeByAlbumId(Integer albumId) {
        // 删除元信息
        albumInfoMapper.deleteById(albumId);
        // 删除关联点赞记录数
        LambdaQueryWrapper<ActionCounts> actionCountsQueryWrapper = new LambdaQueryWrapper<>();
        actionCountsQueryWrapper.eq(ActionCounts::getMessageId,albumId);
        actionCountsService.remove(actionCountsQueryWrapper);
        // 获取该专辑标签列表
        List<Integer> tagIds = albumTagsService.getTagListWithAlbumId(albumId);
        // 该标签下作品数减1
        tagIds.forEach(tagId->{
            tagInfoService.operationWorkCount(tagId,1,Constants.WORK_COUNT_DELETE);
        });
        // 作者作品数量 - 1
        List<Integer> authorIds = albumAuthorService.getAuthorListWithAlbumId(albumId);
        authorIds.forEach(authorId->{
            authorService.operationWorkCount(authorId,1,Constants.WORK_COUNT_DELETE);
        });
        // 社团作品数量 -1
        LambdaQueryWrapper<AlbumInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(AlbumInfo::getId,albumId);
        AlbumInfo albumInfo = getOne(queryWrapper);
        circlesInfoService.operationWorkCount(albumInfo.getCircleId(),1,Constants.WORK_COUNT_DELETE);
        // 删除关联关系
        LambdaQueryWrapper<ArAlbumTag> albumTagWrapper = new LambdaQueryWrapper<>();
        albumTagWrapper.eq(ArAlbumTag::getAlbumId,albumId);
        albumTagsService.remove(albumTagWrapper);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean saveTag(Integer albumId, Integer tagId) {
        LambdaQueryWrapper<ArAlbumTag> albumTagQueryWrapper = new LambdaQueryWrapper<>();
        albumTagQueryWrapper.eq(ArAlbumTag::getAlbumId,albumId);
        albumTagQueryWrapper.eq(ArAlbumTag::getTagId,tagId);
        long count = albumTagsService.count(albumTagQueryWrapper);
        if (count > 0) {
            // 该专辑已有标签 ， 默认用户点赞
            LambdaUpdateWrapper<ActionCounts> actionUpdateWrapper = new LambdaUpdateWrapper<>();
            actionUpdateWrapper.eq(ActionCounts::getMessageId,albumId);
            actionUpdateWrapper.setSql("like_count = like_count + 1");
            return actionCountsService.update(actionUpdateWrapper);
        }
        // 添加用户自定义标签，关联表
        ArAlbumTag arAlbumTag = new ArAlbumTag();
        arAlbumTag.setAlbumId(albumId);
        arAlbumTag.setTagId(tagId);
        arAlbumTag.setStatus(Constants.TAG_LOW_ORIGINALITY);
        boolean flag = albumTagsService.save(arAlbumTag);
        if (!flag) {
            return false;
        }
        //数量 + 1
        tagInfoService.operationWorkCount(tagId,1,Constants.WORK_COUNT_ADD);
        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void editAlbumInfo(AlbumRequest albumRequest) {
        // 先删除所有关联关系
        LambdaQueryWrapper<ArAlbumTag> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ArAlbumTag::getAlbumId,albumRequest.getId());
        //之前有的标签
        List<ArAlbumTag> list = albumTagsService.list(queryWrapper);

        // 现在的标签
        List<Integer> tags = albumRequest.getTags();
        Set<Integer> existTagIds;
        if (!list.isEmpty()) {
            // 先把已经存在的 tagId 收集成 Set，查找更高效
            existTagIds = list.stream()
                    .map(ArAlbumTag::getTagId)
                    .collect(Collectors.toSet());
        } else {
            existTagIds = new HashSet<>();
        }
        if (!existTagIds.isEmpty()){
            // 之前的标签不为空，减少对应作品数
            existTagIds.forEach(tagId->{
                tagInfoService.operationWorkCount(tagId,1,Constants.WORK_COUNT_DELETE);
            });
            // 删除关联关系
            albumTagsService.remove(queryWrapper);
        }
        // 找出还没初始化标签统计表的 tagId 标签统计表不做删除
        List<Integer> noInitTagId = tags.stream()
                .filter(tagId -> !existTagIds.contains(tagId))
                .toList();
        LambdaQueryWrapper<AlbumAuthor> albumAuthorWrapper = new LambdaQueryWrapper<>();
        albumAuthorWrapper.eq(AlbumAuthor::getAlbumId,albumRequest.getId());
        albumAuthorService.remove(albumAuthorWrapper);
        //保存重新保存元信息
        saveOrUpdateGenAlbumInfo(albumRequest);
    }

    @Override
    public List<AlbumRJCode> getAlbumRjCode() {
        return albumInfoMapper.getAlbumRJCode();
    }

    @Override
    public List<Integer> getAlbumsByCircleIds(List<Integer> idList) {
        LambdaQueryWrapper<AlbumInfo> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(AlbumInfo::getCircleId,idList);
        queryWrapper.eq(AlbumInfo::getIsDeleted,false);
        List<AlbumInfo> albumInfoList = list(queryWrapper);
        return albumInfoList.stream().map(AlbumInfo::getId).toList();
    }

    @Override
    public void computedRate() {
        List<TrackInfo> trackInfoList =  trackInfoMapper.getLastDayRecords();
        // 获取半小时数据有发生变动的作品
        List<Integer> albumIds = trackInfoList.stream().map(TrackInfo::getAlbumId).toList();
        // 重新计算该专辑的完播率
        for (Integer albumId : albumIds) {
            List<TrackInfo> trackInfos = trackInfoMapper.getTrackByAlbumId(albumId);
            int size = trackInfos.size();
            BigDecimal sum = trackInfos.stream()
                    .map(TrackInfo::getCompletedViewRate)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            BigDecimal avg = size == 0
                    ? BigDecimal.ZERO
                    : sum.divide(BigDecimal.valueOf(size), 4, RoundingMode.HALF_UP);
            LambdaUpdateWrapper<AlbumInfo> albumUpdateWrapper = new LambdaUpdateWrapper<>();
            albumUpdateWrapper.eq(AlbumInfo::getId,albumId);
            albumUpdateWrapper.eq(AlbumInfo::getIsDeleted,false);
            albumUpdateWrapper.set(AlbumInfo::getCompleteRate,avg);
            update(albumUpdateWrapper);
        }
    }

    @Override
    public void recommendAllHotRank() {
        TopKDTO topK = new TopKDTO(100, new PriorityQueue<HotWorkVo>(100, Comparator.comparing(HotWorkVo::getHot)));
        int limit = 1000;
        // 行为权重表只查一次（因为对所有专辑都一样）
        List<BehaviorWeight> weights = behaviorWeightMapper.selectList(
                new LambdaQueryWrapper<BehaviorWeight>().eq(BehaviorWeight::getIsDel, false)
        );
        Map<String, Double> weightMap = weights.stream()
                .collect(Collectors.toMap(BehaviorWeight::getBehavior, BehaviorWeight::getWeight));
        Integer id = 0;
        LambdaQueryWrapper<ActionCounts> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.gt(ActionCounts::getId,id);
        queryWrapper.eq(ActionCounts::getType,BusinessConstants.BUSINESS_ALBUM);
        queryWrapper.last("limit " + limit);
        List<ActionCounts> albumList = actionCountsService.list(queryWrapper);
        while (!albumList.isEmpty()) {
            albumList.forEach(albumStat -> {
                double hotScore = computeHotScore(albumStat, weightMap);
                HotWorkVo hotWorkVo = new HotWorkVo(hotScore, albumStat.getMessageId());
                topK.add(hotWorkVo);
            });
            // 获取全站的下一批进行处理
            id = albumList.get(albumList.size() - 1).getId();
            albumList = actionCountsService.list(queryWrapper.gt(ActionCounts::getId,id));
        }
        byte[] key = RedisConfig.HOT_RANK.getBytes(StandardCharsets.UTF_8);
        List<HotWorkVo> hotWorkVos = topK.get();
        Double minHot = hotWorkVos.get(0).getHot();


        redisUtil.executePipeline(connection -> {
            for (HotWorkVo hotWork : hotWorkVos) {
                Double hot = hotWork.getHot();
                byte[] member = String.valueOf(hotWork.getAlbumId()).getBytes(StandardCharsets.UTF_8);
                connection.zAdd(key, hot, member);
            }
        });
        redisUtil.removeRangeByScore(RedisConfig.HOT_RANK,minHot,0);
    }
    @Override
    public double computeHotScore(ActionCounts actionCounts,Map<String, Double> weightMap) {
        // 各行为得分
        double clickScore = actionCounts.getClickCount() * weightMap.getOrDefault(Constants.ACTION_CLICK, 0.50);
        double favScore   = actionCounts.getFavoriteCount() * weightMap.getOrDefault(Constants.ACTION_FAV, 3.00);
        double likeScore  = actionCounts.getLikeCount() * weightMap.getOrDefault(Constants.ACTION_GREAT, 1.00);
        double playScore  = actionCounts.getPlayCount() * weightMap.getOrDefault(Constants.ACTION_PLAY, 1.00);

        // 完播率加权
        double completionRate = actionCounts.getCompleteRate() != null ? actionCounts.getCompleteRate().doubleValue() : 0.0;
        double completionWeight = Math.pow(completionRate, 1.5);
        double completeViewScore = actionCounts.getPlayCount() * completionWeight;

        // 时间衰减因子（新内容加成）
        long daysSinceCreated = 1;
        if (actionCounts.getCreateTime() != null){
            daysSinceCreated = ChronoUnit.DAYS.between(
                    actionCounts.getCreateTime().toInstant(),
                    Instant.now()
            );
        }

        double timeFactor = Math.max(0.1, 1.0 - (daysSinceCreated / 365.0));
        // 最终热度值
        return Math.floor((clickScore + favScore + likeScore + playScore + completeViewScore) * timeFactor);
    }

    @Override
    public List<AlbumResponse> getAlbumInfoByIds(List<Integer> ids) {
        if (ids != null && ids.isEmpty()) {
            return Collections.emptyList();
        }
        return albumInfoMapper.getAlbumByIds(ids);
    }

    @Override
    public AlbumTrackResponse getAlbumTrackById(Integer albumId) {
        AlbumResponse allAlbumInfoById = albumInfoMapper.getAllAlbumInfoById(albumId);
        AlbumTrackResponse albumTrackResponse = new AlbumTrackResponse();
        albumTrackResponse.setTitle(allAlbumInfoById.getAlbumTitle());
        albumTrackResponse.setId(allAlbumInfoById.getId());
        albumTrackResponse.setCoverUrl(allAlbumInfoById.getCoverUrl());
        List<TrackResponse> trackInfo = trackInfoMapper.getTrackInfo(albumId);
        albumTrackResponse.setTrackInfo(trackInfo);
        List<Integer> authorIds = albumAuthorService.getAuthorListWithAlbumId(albumId);
        LambdaQueryWrapper<Author> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(Author::getId, authorIds);
        List<Author> authors = authorService.list(queryWrapper);
        albumTrackResponse.setAuthor(authors);
        return albumTrackResponse;
    }

}




